﻿using Sustainalytics.DataLayer;
using Sustainalytics.Utils;
using System;
using System.Configuration;
using System.IO;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Threading.Tasks;
using System.Web.Http;
using Sustainalytics.Governance.BusinessLogic.Helpers;
using System.Web.Http.Cors;
using Sustainalytics.Utils.Configuration;
using Sustainalytics.AwsS3.Client;
using System.Linq;
using Sustainalytics.Governance.BusinessLogic.PdfMetadata;
using Sustainalytics.DataLayer.Shared;
using Sustainalytics.Entities.Governance;

namespace Sustainalytics.Governance.Service
{
    [EnableCors(origins: "*", headers: "*", methods: "*")]
    [LogControllerFilter(true, true, false)]
    [RoutePrefix("api/v1/filesclientplatform")]
	public class GovernanceClientPlatformAttachmentsController : ApiController
	{
        private readonly string baseUrl;
	    private readonly IFileRepository _fileRepository;
        private readonly string _controllerRoutePrefix;
        //private readonly string _bucketName;
        //private readonly string _prefix;
        private IGovernancePdfMetadataManager _governancePdfMetadataManager;
        private readonly IRepositoryCollection<GovernanceInsightInputFile> _governanceInputFileRepositoryWithFiles;

        public GovernanceClientPlatformAttachmentsController()
	    {

            baseUrl = ConfigurationManager.AppSettings["ClientPlatformUrl"];
            _controllerRoutePrefix = "api/v1/filesclientplatform";
            var connectionString = ConfigurationManager.ConnectionStrings["GovernanceInputFile"].ConnectionString;
            _fileRepository = new FileRepository(connectionString);

            //_bucketName = SettingsHelper.Read("s3-governance-reports", "dev-globalaccess-europe/GovernanceReports");
            //_prefix = SettingsHelper.Read("s3prefix-governance-reports", "Dev");

            IGovernancePdfProfileMetadataRepository governancePdfProfileMetadataRepository = new GovernancePdfProfileMetadataRepository(connectionString);
            _governanceInputFileRepositoryWithFiles = new RepositoryCollectionWithFile<GovernanceInsightInputFile>(connectionString);
            _governancePdfMetadataManager = new GovernancePdfMetadataManager(governancePdfProfileMetadataRepository, _governanceInputFileRepositoryWithFiles, "");
        }

        public GovernanceClientPlatformAttachmentsController(IFileRepository fileRepository, string baseUrl)
        {
            this.baseUrl = baseUrl;
            this._fileRepository = fileRepository;
        }

        [HttpGet]
        [Route("{id}")]
        public virtual HttpResponseMessage Get([FromUri] Guid id)
        {
            try
            {         
                var result = Request.CreateResponse(HttpStatusCode.OK);
                var fileData = _fileRepository.GetDownloadStream(id);
                if (fileData != null)
                {
                    var mimeType = fileData.Item3;
                    if (mimeType == null)
                    {
                        var ext = Path.GetExtension(fileData.Item2);
                        switch (ext)
                        {
                            case ".pdf":
                                mimeType = "application/pdf";
                                break;
                            case ".jpg":
                            case ".jpeg":
                                mimeType = "application/jpeg";
                                break;                           
                            case ".png":
                                mimeType = "application/png";
                                break;
                        }
                    }
                    result.Content = new PushStreamContent((outStream, httpContent, context) =>
                    {
                        using (fileData.Item1)
                        {
                            fileData.Item1.CopyTo(outStream);
                        }
                        outStream.Close();
                    });
                    result.Content.Headers.Add("Content-Disposition", "attachement; filename=" + Uri.EscapeDataString(fileData.Item2.Replace(".pdf", "") + "_" + DateTime.Now.ToString("dd-MM-yyyy") + ".pdf"));
                    result.Content.Headers.ContentType = new MediaTypeHeaderValue(mimeType);
                    return result;
                }
                return Request.CreateResponse(HttpStatusCode.NotFound);
            }
            catch (Exception ex)
            {
                GovernanceEventSource.Log.LogError(ex);
                return Request.CreateResponse(HttpStatusCode.InternalServerError);
            }
        }

        [HttpGet]
        [Route("")]
        public virtual HttpResponseMessage Get([FromUri] Guid id, String reportType)
        {
            try
            {
                var result = Request.CreateResponse(HttpStatusCode.OK);
                var fileData = _governancePdfMetadataManager.LoadFileFromS3(id, reportType);
                if (fileData != null)
                {
                    //var ext = Path.GetExtension(fileData.Item2);
                    //switch (ext)
                    //{
                    //    case ".pdf":
                    //        mimeType = "application/pdf";
                    //        break;
                    //    case ".jpg":
                    //    case ".jpeg":
                    //        mimeType = "application/jpeg";
                    //        break;
                    //    case ".png":
                    //        mimeType = "application/png";
                    //        break;
                    //}
                    var mimeType = "application/pdf";
                    result.Content = new PushStreamContent((outStream, httpContent, context) =>
                    {
                        outStream = new MemoryStream(fileData);
                        outStream.Close();
                    });

                    // TO DO: Add later
                    //result.Content.Headers.Add("Content-Disposition", "attachement; filename=" + Uri.EscapeDataString(fileData.Item2.Replace(".pdf", "") + "_" + DateTime.Now.ToString("dd-MM-yyyy") + ".pdf"));
                    result.Content.Headers.ContentType = new MediaTypeHeaderValue(mimeType);
                    return result;
                }
                return Request.CreateResponse(HttpStatusCode.NotFound);
            }
            catch (Exception ex)
            {
                GovernanceEventSource.Log.LogError(ex);
                return Request.CreateResponse(HttpStatusCode.InternalServerError);
            }
        }

        [HttpPost]
        [Route("")]
        public virtual Task<HttpResponseMessage> Post([FromUri] Guid companyId, int governancePdfType)
        {
            try
            {
                //var companyId = Request.Headers.GetValues("CompanyId").FirstOrDefault();
                //string governancePdfType = Request.Headers.GetValues("GovernancePdfType").FirstOrDefault();
                string filename = string.Empty;

                // S3 File repository
                Task<Stream> fileContent = Request.Content.ReadAsStreamAsync();
                var result = fileContent.ContinueWith(task =>
                {
                    if (task.IsCanceled || task.IsFaulted)
                        throw new HttpRequestException();
                    byte[] fileContentByteArray;
                    using (var memoryStream = new MemoryStream())
                    {
                        task.Result.CopyTo(memoryStream);
                        fileContentByteArray = memoryStream.ToArray();
                    }
                    GovernancePdfType type = (GovernancePdfType)governancePdfType;

                    if (type == GovernancePdfType.Insight)
                    {
                        Guid fileId = Guid.NewGuid();
                        filename = $"{companyId}_{fileId}.pdf";
                        if (_governancePdfMetadataManager.SaveFileInS3(filename, type.ToString(), fileContentByteArray))
                            return Request.CreateResponse(HttpStatusCode.OK, new { filename = filename, fileId = fileId.ToString() });
                        else
                            return Request.CreateResponse(HttpStatusCode.ServiceUnavailable);
                    }
                    else
                    {
                        filename = $"{companyId}.pdf";
                        if (_governancePdfMetadataManager.SaveFileInS3(filename, type.ToString(), fileContentByteArray))
                            return Request.CreateResponse(HttpStatusCode.OK, new { filename = filename });
                        else
                            return Request.CreateResponse(HttpStatusCode.ServiceUnavailable);
                    }
                });
                return result;
            }
            catch (Exception ex)
            {
                GovernanceEventSource.Log.LogError(ex);
                return (new Task<HttpResponseMessage>(() => Request.CreateResponse(HttpStatusCode.InternalServerError)));               
            }
        }

        [HttpPost]
        [Route("")]
        public virtual Task<HttpResponseMessage> Post([FromUri] Guid companyId, int governancePdfType, Guid fileId)
        {
            try
            {
                //var companyId = Request.Headers.GetValues("CompanyId").FirstOrDefault();
                //string governancePdfType = Request.Headers.GetValues("GovernancePdfType").FirstOrDefault();
                string filename = string.Empty;

                // S3 File repository
                Task<Stream> fileContent = Request.Content.ReadAsStreamAsync();
                var result = fileContent.ContinueWith(task =>
                {
                    if (task.IsCanceled || task.IsFaulted)
                        throw new HttpRequestException();
                    byte[] fileContentByteArray;
                    using (var memoryStream = new MemoryStream())
                    {
                        task.Result.CopyTo(memoryStream);
                        fileContentByteArray = memoryStream.ToArray();
                    }
                    GovernancePdfType type = (GovernancePdfType)governancePdfType;

                    if (type == GovernancePdfType.Insight)
                    {
                        filename = $"{companyId}_{fileId}.pdf";
                        if (_governancePdfMetadataManager.SaveFileInS3(filename, type.ToString(), fileContentByteArray))
                            return Request.CreateResponse(HttpStatusCode.OK, new { filename = filename, fileId = fileId.ToString() });
                        else
                            return Request.CreateResponse(HttpStatusCode.ServiceUnavailable);
                    }
                    else
                    {
                        filename = $"{companyId}.pdf";
                        if (_governancePdfMetadataManager.SaveFileInS3(filename, type.ToString(), fileContentByteArray))
                            return Request.CreateResponse(HttpStatusCode.OK, new { filename = filename });
                        else
                            return Request.CreateResponse(HttpStatusCode.ServiceUnavailable);
                    }
                });
                return result;
            }
            catch (Exception ex)
            {
                GovernanceEventSource.Log.LogError(ex);
                return (new Task<HttpResponseMessage>(() => Request.CreateResponse(HttpStatusCode.InternalServerError)));
            }
        }

        [HttpPut]
        [Route("{id}")]
        public virtual Task<HttpResponseMessage> Put([FromUri] Guid id)
		{
            try
            {               
                var newid = Guid.NewGuid();
                var filename = Request.Content.Headers.ContentDisposition.FileName.Replace(@"\", string.Empty).Replace("\"", string.Empty);
                var contentType = Request.Content.Headers.ContentType.ToString();
                var mongoData = _fileRepository.UpdateFile(id, newid, filename, contentType);
                var fileUrl = ComposeFileUrl.GetUrl(mongoData.Item2, baseUrl, _controllerRoutePrefix);


                var result = Request.Content.ReadAsStreamAsync().ContinueWith(task =>
                {
                    if (task.IsCanceled || task.IsFaulted)
                        throw new HttpRequestException();

                    using (mongoData.Item1)
                    {
                        task.Result.CopyTo(mongoData.Item1);
                        return Request.CreateResponse(HttpStatusCode.OK, new { fileUrl = fileUrl, id = mongoData.Item2 });
                    }
                });
                return result; 
            }
            catch (Exception ex)
            {
                GovernanceEventSource.Log.LogError(ex);
                return (new Task<HttpResponseMessage>(() => Request.CreateResponse(HttpStatusCode.InternalServerError)));                           
            }
		}
	}
}

